﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using NielsHebling.UnitTestResultViewerForSL.Controls;
using NielsHebling.UnitTestResultViewerForSL.Core.Logic;

namespace NielsHebling.UnitTestResultViewerForSL
{
    /// <summary>
    /// Interaction logic for MainResultsView.xaml
    /// </summary>
    public partial class MainResultsView : UserControl
    {
        private SessionInformation _session;
        private TestExecutionWorker _worker;

        public MainResultsView()
        {
            InitializeComponent();

            _session = new SessionInformation();
            _worker = new TestExecutionWorker();

            Application.Current.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(Current_DispatcherUnhandledException);
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

            //Set assemblies 
            Binding assemblyBinding = new Binding("ProjectXapItems")
            {
                Source = _session,
                Mode = BindingMode.TwoWay
            };
            this.ResultListControl.SetBinding(ResultList.AssemblyItemsProperty, assemblyBinding);

            //Set option
            Binding runOnBuildBinding = new Binding("RunOnBuildDone")
            {
                Source = _session,
                Mode = BindingMode.TwoWay
            };
            this.ResultListControl.SetBinding(ResultList.RunOnBuildDoneProperty, runOnBuildBinding);

            Binding selectedAssemblyItemBinding = new Binding("SelectedProjectXapItem")
            {
                Source = _session,
                Mode = BindingMode.OneWayToSource
            };
            this.ResultListControl.SetBinding(ResultList.SelectedAssemblyItemProperty, selectedAssemblyItemBinding);

            Binding itemsBinding = new Binding("Items")
            {
                Source = _worker.ResultItems,
                Mode = BindingMode.TwoWay
            };
            this.ResultListControl.SetBinding(ResultList.ItemsProperty, itemsBinding);

            Binding summaryBinding = new Binding("TestsTotal")
            {
                Source = _session.CombinedTestResult,
                Mode = BindingMode.OneWay
            };
            this.ResultListControl.SetBinding(ResultList.LabelTestRunSummaryTextProperty, summaryBinding);

            Binding runningBinding = new Binding("IsRunning")
            {
                Source = _session,
                Mode = BindingMode.TwoWay
            };
            this.ResultListControl.SetBinding(ResultList.IsRunningProperty, runningBinding);

            //Control event registration
            this.ResultListControl.TriggerTest += new RoutedEventHandler(ResultListControl_TriggerTest);
            this.ResultListControl.RefreshAssemblies += new RoutedEventHandler(ResultListControl_RefreshAssemblies);


            //Set events
            VsShellAbstractionLayer.Instance.SolutionEvents.Opened += new EnvDTE._dispSolutionEvents_OpenedEventHandler(SolutionEvents_Opened);
            VsShellAbstractionLayer.Instance.SolutionEvents.BeforeClosing += new EnvDTE._dispSolutionEvents_BeforeClosingEventHandler(SolutionEvents_BeforeClosing);
            VsShellAbstractionLayer.Instance.SolutionEvents.ProjectAdded += new EnvDTE._dispSolutionEvents_ProjectAddedEventHandler(SolutionEvents_ProjectAdded);
            VsShellAbstractionLayer.Instance.SolutionEvents.ProjectRemoved += new EnvDTE._dispSolutionEvents_ProjectRemovedEventHandler(SolutionEvents_ProjectRemoved);
            VsShellAbstractionLayer.Instance.SolutionEvents.ProjectRenamed += new EnvDTE._dispSolutionEvents_ProjectRenamedEventHandler(SolutionEvents_ProjectRenamed);
            VsShellAbstractionLayer.Instance.BuildEvents.OnBuildDone += new EnvDTE._dispBuildEvents_OnBuildDoneEventHandler(BuildEvents_OnBuildDone);
        }

        void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            VsShellAbstractionLayer.Instance.Trace(e.Exception.ToString());
        }

        void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            VsShellAbstractionLayer.Instance.Trace(e.ExceptionObject.ToString());
        }

        #region SolutionEvents
        void SolutionEvents_ProjectRenamed(EnvDTE.Project Project, string OldName)
        {
            //Refresh list
            _session.ProjectXapItems = VsShellAbstractionLayer.Instance.GetXapProjectMapping();
        }

        void SolutionEvents_ProjectRemoved(EnvDTE.Project Project)
        {
            //Refresh list
            _session.ProjectXapItems = VsShellAbstractionLayer.Instance.GetXapProjectMapping();
        }

        void SolutionEvents_ProjectAdded(EnvDTE.Project Project)
        {
            //Refresh list
            _session.ProjectXapItems = VsShellAbstractionLayer.Instance.GetXapProjectMapping();
        }

        void SolutionEvents_BeforeClosing()
        {
            //Dispose and clear sln/prj related stuff
        }

        void SolutionEvents_Opened()
        {
            //Get initial list
            _session.ProjectXapItems = VsShellAbstractionLayer.Instance.GetXapProjectMapping();
        }
        #endregion

        void ResultListControl_RefreshAssemblies(object sender, RoutedEventArgs e)
        {
            //Refresh list
            _session.ProjectXapItems = VsShellAbstractionLayer.Instance.GetXapProjectMapping();
        }

        #region Test Trigger
        void ResultListControl_TriggerTest(object sender, RoutedEventArgs e)
        {
            ExecuteTest();
        }

        void BuildEvents_OnBuildDone(EnvDTE.vsBuildScope Scope, EnvDTE.vsBuildAction Action)
        {
            if (_session.RunOnBuildDone)
            {
                ExecuteTest();
            }
        }

        private void ExecuteTest()
        {
            if (_session.SelectedProjectXapItem != null)
            {
                List<string> xapList = _session.VerifyXapItems();
                if (xapList != null && xapList.Count > 0)
                {
                    Mouse.OverrideCursor = Cursors.Wait;
                    _worker = new TestExecutionWorker();
                    _worker.InitializeTasks(System.IO.Path.GetDirectoryName(VsShellAbstractionLayer.Instance.GetSolution().Properties.Item("Path").Value.ToString()), xapList, this.ResultListControl);
                    _worker.RunTasks();
                    Mouse.OverrideCursor = null;
                }
            }
            else
            {
                MessageBox.Show("Please select an assembly to test.", "Select assembly", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }
        #endregion         
    }
}